namespace ManoMachine.Emulator
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;

    public class Memory : IEnumerable<MemoryItem>
    {
        private static Memory memoryInastance = new Memory();

        ObservableCollection<MemoryItem> memoryWords = new ObservableCollection<MemoryItem>(new MemoryItem[4096]);

        private Memory()
        {
            for (ushort i = 0; i < memoryWords.Count; i++)
            {
                memoryWords[i] = new MemoryItem() { Address = i };
            }
        }

        public static Memory Current
        {
            get
            {
                return memoryInastance;
            }
        }

        public short Read(ushort address, AddressModes addressMode)
        {
            short int16 = Convert.ToInt16(address.ToString("X"), 16);
            if (addressMode == AddressModes.Indirect)
            {
                short memoryWord = this.memoryWords[int16].Value;
                int16 = Convert.ToInt16(memoryWord.ToString("X"), 16);
                return this.memoryWords[int16].Value;
            }
            else
            {
                return this.memoryWords[int16].Value;
            }
        }

        public void Write(short value, ushort address, AddressModes addressModes)
        {
            short int16 = Convert.ToInt16(address.ToString("X"), 16);
            if (addressModes == AddressModes.Indirect)
            {
                // hack
                //                if (this.memoryWords[int16] == null)
                //                {
                //                    this.memoryWords[int16] = new MemoryItem();
                //                }
                short memoryWord = this.memoryWords[int16].Value;
                int16 = Convert.ToInt16(memoryWord.ToString("X"), 16);
                this.memoryWords[int16].Value = value;
            }
            else if (addressModes == AddressModes.Direct)
            {
                // hack
                //                if (this.memoryWords[int16] == null)
                //                {
                //                    this.memoryWords[int16] = new MemoryItem();
                //                }

                this.memoryWords[int16].Value = value;
            }
        }

        public IEnumerator<MemoryItem> GetEnumerator()
        {
            return memoryWords.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
    }
}